package com.work.device.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.work.device.mapper.DeviceInfoMapper;
import com.work.device.mapper.DeviceMapper;
import com.work.device.mapper.IndexMapper;
import com.work.device.pojo.Addstatus;
import com.work.device.pojo.Device;
import com.work.device.pojo.DeviceInfo;
import com.work.device.pojo.Index;
import com.work.device.service.DeviceService;
import com.work.utils.IdWorker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.function.LongBinaryOperator;

import static com.work.utils.Page.pageNum;
import static com.work.utils.Page.pageSize;

@Service
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private DeviceInfoMapper deviceInfoMapper;
    @Autowired
    private IndexMapper indexMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RedisTemplate redisTemplate;

    public static final String DEVICE_BACKUP = "device_backup";
    public static String ALL_DEVICES;
    public static final String total = "total";
    public static final String CODELIST = "codelist";
    public static final String NAMELIST = "namelist";
    public static final String TYPELIST = "typelist";
    public static final String BRANDLIST = "brandlist";
    public static final String MODELLIST = "modellist";
    public static final String DATANAMELIST = "dataNamelist";
    //默认当前页面
    public static final Integer DEFAULT_PAGENUM = 1;
    //默认分页大小
    public static final Integer DEFAULT_PAGESIZE = 10;


    /**
     * 分页查询
     *
     * @param serrchMap 搜索封装的map
     * @return 搜索结果
     */
    @Override
    public Map<String, Object> pageQuery(Map<String, Object> serrchMap) {
        //创建返回map集合
        Map<String, Object> resultMap = new HashMap<>();
        //处理map为空的情况
        if (serrchMap == null) {
            //默认设置,设置分页页码是1,分页大小是10
            serrchMap = new HashMap<>();
        }
        //处理map中,没有pageNum和pageSize的情况,并设置默认值,pageNum=1,pageSize=10
        //获取当前页码
        Integer pageNum = DEFAULT_PAGENUM;
        //获取分页大小
        Integer pageSize = DEFAULT_PAGESIZE;
        //如果
        if (serrchMap.get("pageNum") != null) {
            //默认设置,设置分页页码是1,分页大小是10
            pageNum = Integer.parseInt((String) serrchMap.get("pageNum"));
            serrchMap.put("pageNum", pageNum);
        }
        if (serrchMap.get("pageSize") != null) {
            //默认设置,设置分页页码是1,分页大小是10
            pageSize = Integer.parseInt((String) serrchMap.get("pageSize"));
            serrchMap.put("pageSize", pageSize);
        }

        //获取查询条件
        // 设备编码
        String code = (String) serrchMap.get("code");
        // 设备名称
        String name = (String) serrchMap.get("name");
        // 设备类型
        String type = (String) serrchMap.get("type");
        // 设备品牌
        String brand = (String) serrchMap.get("brand");
        // 设备型号
        String model = (String) serrchMap.get("model");
        //计量名称
        String dataName = (String) serrchMap.get("dataName");
        //按照价格排序
        String order = (String) serrchMap.get("order");

        //价格区间    注意:价格数据库中以分为单位
        //0-1000 1000-5000 5000-10000 10000-30000 30000
        String priceRange = (String) serrchMap.get("price");
        //设置价格最小区间
        Long minPrice = null;
        //设置价格最大区间
        Long maxPrice = null;
        if (priceRange != null) {
            //有了价格区间,默认升序排序
            String[] priceSplit = priceRange.split("-");
            if (priceSplit.length == 2) {
                //有两个去取
                String minPriceStr = priceSplit[0];
                minPrice = Long.parseLong(minPriceStr);
                String maxPriceStr = priceSplit[1];
                maxPrice = Long.parseLong(maxPriceStr);

            } else {
                String minPriceStr = priceSplit[0];
                minPrice = Long.parseLong(minPriceStr);
            }
        }

        //封装resultMap
        resultMap.put("pageNum", pageNum);
        resultMap.put("pageSize", pageSize);

        //redis中的键
        ALL_DEVICES = pageNum + "_" + pageSize;
        if (code != null) {
            ALL_DEVICES += code;
        }
        if (name != null) {
            ALL_DEVICES += name;
        }
        if (type != null) {
            ALL_DEVICES += type;
        }
        if (brand != null) {
            ALL_DEVICES += brand;
        }
        if (model != null) {
            ALL_DEVICES += model;
        }
        if (priceRange != null) {
            ALL_DEVICES += priceRange;
        }
        if (dataName != null) {
            ALL_DEVICES += dataName;
        }
        if (order != null) {
            ALL_DEVICES += order;
        }

        //封装resultMap集合
        Object codeList = redisTemplate.opsForHash().get(DEVICE_BACKUP, CODELIST);
        if (codeList != null) {
            //从redis中快速获取
            resultMap.put("codeList", codeList);
        } else {
            Map<String, Object> deviceInfo = this.findDeviceInfo();
            codeList = deviceInfo.get(CODELIST);
            resultMap.put("codeList", codeList);
        }
        Object nameList = redisTemplate.opsForHash().get(DEVICE_BACKUP, NAMELIST);
        if (nameList != null) {
            //从redis中快速获取
            resultMap.put("nameList", nameList);
        } else {
            Map<String, Object> deviceInfo = this.findDeviceInfo();
            nameList = deviceInfo.get(NAMELIST);
            resultMap.put("nameList", nameList);
        }
        Object typeList = redisTemplate.opsForHash().get(DEVICE_BACKUP, TYPELIST);
        if (typeList != null) {
            //从redis中快速获取
            resultMap.put("typeList", typeList);
        } else {
            Map<String, Object> deviceInfo = this.findDeviceInfo();
            typeList = deviceInfo.get(TYPELIST);
            resultMap.put("typeList", typeList);
        }
        Object brandList = redisTemplate.opsForHash().get(DEVICE_BACKUP, BRANDLIST);
        if (brandList != null) {
            //从redis中快速获取
            resultMap.put("brandList", brandList);
        } else {
            Map<String, Object> deviceInfo = this.findDeviceInfo();
            brandList = deviceInfo.get(BRANDLIST);
            resultMap.put("brandList", brandList);
        }
        Object modelList = redisTemplate.opsForHash().get(DEVICE_BACKUP, MODELLIST);
        if (modelList != null) {
            //从redis中快速获取
            resultMap.put("modelList", modelList);
        } else {
            Map<String, Object> deviceInfo = this.findDeviceInfo();
            modelList = deviceInfo.get(MODELLIST);
            resultMap.put("modelList", modelList);
        }
        Object dataNameList = redisTemplate.opsForHash().get(DEVICE_BACKUP, DATANAMELIST);
        if (dataNameList != null) {
            //从redis中快速获取
            resultMap.put("dataNameList", dataNameList);
        } else {
            Map<String, Object> indexInfo = this.findIndexInfo();
            dataNameList = indexInfo.get(DATANAMELIST);
            resultMap.put("dataNameList", dataNameList);
        }

        //先从redis中获取deviceList,封装resultMap集合
        Object redisDevices = redisTemplate.opsForHash().get(DEVICE_BACKUP, ALL_DEVICES);
        if (redisDevices != null) {
            //Redis快速获取
            long total = ((PageInfo<Device>) redisDevices).getTotal();
            //封装到resultMap
            resultMap.put("total", total);
            List<Device> devicelist = ((PageInfo<Device>) redisDevices).getList();
            //封装到resultMap
            resultMap.put("deviceList", devicelist);
            return resultMap;
        }

        //开启分页
        PageHelper.startPage(pageNum, pageSize);
        //先在Redis中查询
        List<Device> devices = null;
        //如果map中只有pageNum和pageSize两个值,查询全部
        if (serrchMap.size() == 2) {
            devices = deviceMapper.selectAll();

        } else {
            Example example = new Example(Device.class);
            Example.Criteria criteria = example.createCriteria();
            if (code != null) {
                criteria.andEqualTo("code", code);
            }
            if (name != null) {
                criteria.andEqualTo("name", name);
            }
            if (type != null) {
                criteria.andEqualTo("type", type);
            }
            if (brand != null) {
                criteria.andEqualTo("brand", brand);
            }
            if (model != null) {
                criteria.andEqualTo("model", model);
            }

            //price
            if (priceRange != null) {
                if (maxPrice != null) {
                    criteria.andBetween("price", minPrice, maxPrice);
                } else {
                    criteria.andGreaterThanOrEqualTo("price", minPrice);
                }
            }
            //数据指标
            if (dataName != null) {
                List<Long> didList = this.getDidsByDataName(dataName);
                if (didList != null && didList.size() > 0) {
                    criteria.andIn("id", didList);
                }
            }
            //order
            if (order != null) {
                if ("DESC".equals(order)) {
                    example.orderBy("price").desc();
                } else if ("ASC".equals(order)) {
                    example.orderBy("price").asc();
                }
            }
            //map中有其他参数,根据条件查询
            devices = deviceMapper.selectByExample(example);
            // System.out.println(deviceList);
        }
        PageInfo<Device> deviceList = new PageInfo<Device>(devices);
        System.out.println();
        System.out.println(deviceList);
        System.out.println();
        resultMap.put("deviceList", deviceList.getList());
        long total = deviceList.getTotal();
        resultMap.put("total", total);
        redisTemplate.boundHashOps(DEVICE_BACKUP).put(ALL_DEVICES, deviceList);

        return resultMap;
    }


    /**
     * 获得dids
     *
     * @param dataName 数据指标名称
     * @return 设备id集合
     */
    private List<Long> getDidsByDataName(String dataName) {
        Example example = new Example(Index.class);
        Example.Criteria criteria = example.createCriteria();
        //根据计量名称查询计量id
        criteria.andEqualTo("dataName", dataName);
        List<Index> indices = indexMapper.selectByExample(example);
       /* Index index=new Index();
        index.setDataName(dataName);*/
        List<Index> indexList = indexMapper.selectByExample(example);
        if (indexList != null && indexList.size() > 0) {
            //根据测量iid查询设备id
            List<Long> didList = deviceInfoMapper.findDeviceIdByIid(indexList.get(0).getId());
            return didList;
        }
        return null;
    }

    /**
     * 获取设备信息
     *
     * @return 设备信息
     */
    private Map<String, Object> findDeviceInfo() {
        Map<String, Object> findMap = new HashMap<>();
        List<Device> deviceList = deviceMapper.selectAll();
        if (deviceList != null && deviceList.size() > 0) {
            Set<String> codeSet = new HashSet<>();
            Set<String> nameSet = new HashSet<>();
            Set<String> typeSet = new HashSet<>();
            Set<String> brandSet = new HashSet<>();
            Set<String> modelSet = new HashSet<>();

            for (Device device : deviceList) {
                //codeList
                if (device.getCode() != null) {
                    codeSet.add(device.getCode());
                }
                //nameList
                if (device.getName() != null) {
                    nameSet.add(device.getName());
                }
                //typeList
                if (device.getType() != null) {
                    typeSet.add(device.getType());
                }
                //brandList
                if (device.getBrand() != null) {
                    brandSet.add(device.getBrand());
                }
                //modelList
                if (device.getModel() != null) {
                    modelSet.add(device.getModel());
                }

            }
            //存在findMap中
            findMap.put(CODELIST, codeSet);
            findMap.put(NAMELIST, nameSet);
            findMap.put(TYPELIST, typeSet);
            findMap.put(BRANDLIST, brandSet);
            findMap.put(MODELLIST, modelSet);
            //存到redis中
            redisTemplate.opsForHash().put(DEVICE_BACKUP, CODELIST, codeSet);
            redisTemplate.opsForHash().put(DEVICE_BACKUP, NAMELIST, nameSet);
            redisTemplate.opsForHash().put(DEVICE_BACKUP, TYPELIST, typeSet);
            redisTemplate.opsForHash().put(DEVICE_BACKUP, BRANDLIST, brandSet);
            redisTemplate.opsForHash().put(DEVICE_BACKUP, MODELLIST, modelSet);
        }

        return findMap;
    }

    /**
     * 获取数据指标信息
     *
     * @return 数据指标信息
     */
    private Map<String, Object> findIndexInfo() {
        Map<String, Object> findMap = new HashMap<>();
        List<Index> indexList = indexMapper.selectAll();
        if (indexList != null && indexList.size() > 0) {
            Set<String> indexSet = new HashSet<>();
            for (Index index : indexList) {
                //codeList
                if (index.getDataName() != null) {
                    indexSet.add(index.getDataName());
                }
            }
            findMap.put(DATANAMELIST, indexSet);
            //存在redis中
            redisTemplate.opsForHash().put(DEVICE_BACKUP, DATANAMELIST, indexSet);
        }
        return findMap;
    }

    /**
     * 新增设备
     *
     * @param map 封装设备信息
     * @return
     */
    @Override
    @Transactional
    public Addstatus add(Map<String, Object> map) {

        String range = (String) map.get("range");
        String accurancy = (String) map.get("accurancy");
        String resolvingPower = (String) map.get("resolving_power");
        String dataName = (String) map.get("dataName");
        //判断是否有数据指标
        if (range != null || accurancy != null || resolvingPower != null) {
            if (dataName == null) {
                return Addstatus.ADDPARAMERROR;
            }
        }
        //判断设备是否更新
        Boolean flag=false;

        String code = (String) map.get("code");
        String name = (String) map.get("name");
        String type = (String) map.get("type");
        Long price = Long.parseLong( map.get("price")+"");
        String brand = (String) map.get("brand");
        String model = (String) map.get("model");
        String scenarios = (String) map.get("scenarios");
        String image = (String) map.get("image");
        String images = (String) map.get("images");
        String param = (String) map.get("param");
        String info = (String) map.get("info");
        //新增设备
        Device device = new Device();
        device.setCode(code);
        device.setName(name);
        device.setBrand(brand);
        device.setModel(model);
        device.setType(type);
        Example deviceExample = new Example(Device.class);
        Example.Criteria deviceCriteria = deviceExample.createCriteria();
        deviceCriteria.andEqualTo("code", code);
        deviceCriteria.andEqualTo("name", name);
        deviceCriteria.andEqualTo("brand", brand);
        deviceCriteria.andEqualTo("model", model);
        deviceCriteria.andEqualTo("type", type);
        List<Device> devices = deviceMapper.selectByExample(deviceExample);

        if (devices != null && devices.size() > 0) {
            device.setId(devices.get(0).getId());
        } else {
            long did = idWorker.nextId();
            device.setId(did);
        }

        //前端传过来的是分单位,数据库设置的是以分为单位
        device.setPrice(price);
        device.setScenarios(scenarios);
        device.setImage(image);
        device.setImages(images);
        if (devices == null || devices.size() <= 0) {
            deviceMapper.insertSelective(device);
            flag=true;
        }

        //向设备详细表中添加数据
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.setId(idWorker.nextId());
        deviceInfo.setDid(device.getId());
        deviceInfo.setInfo(info);
        deviceInfo.setParam(param);
        //设备详细信息不要重复添加
        if (devices == null || devices.size() <= 0) {
            Integer indoResult = deviceInfoMapper.addInfo(deviceInfo);
        }

        //向设备与指标关联表中添加数据
        if (dataName==null){
            if (flag){
                return Addstatus.ADDSUCCESS;
            }else {
                return Addstatus.ADDREPEAT;
            }
        }
        //查询数据指标
        Example example = new Example(Index.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("dataName", dataName);
        Index index = indexMapper.selectOneByExample(example);
        Long iid = index.getId();

        //设备与数据指标关联表中是否存在相同的了
        Integer exist = deviceInfoMapper.exist(device.getId(), iid);
        //List<Long> deviceIds = deviceInfoMapper.findDeviceIdByIid(iid);
        if (exist != 0) {
            //数据指标不要重复添加
            if (devices != null && devices.size() > 0) {
                return Addstatus.ADDREPEAT;
            }
        }

        deviceInfo.setDiid(idWorker.nextId());
        deviceInfo.setIid(iid);
        deviceInfo.setRange(range);
        deviceInfo.setAccuracy(accurancy);
        deviceInfo.setResolvingPower(resolvingPower);
        deviceInfo.setUnit(dataName);

        Integer indexResult = deviceInfoMapper.addDeviceAndIndex(deviceInfo);

        //添加成功,删除redis中的数据,进行缓存同步
        if (redisTemplate.hasKey(DEVICE_BACKUP)) {
            redisTemplate.delete(DEVICE_BACKUP);
        }
        return Addstatus.ADDSUCCESS;
    }

    /**
     * 根据设备id更新设备
     *
     * @param device 设备
     * @return
     */
    @Override
    @Transactional
    public Integer update(Device device) {
        //更新设备
        int deviceResult = deviceMapper.updateByPrimaryKeySelective(device);
        if (deviceResult == 1) {
            //更新成功,删除redis中的数据,进行缓存同步
            if (redisTemplate.hasKey(DEVICE_BACKUP)) {
                redisTemplate.delete(DEVICE_BACKUP);
            }
        }
        return deviceResult;
    }


    /**
     * 根据设备id删除设备
     *
     * @param id 设备id
     * @return
     */
    @Override
    @Transactional
    public Integer delete(Long id) {
        //删除设备
        int deviceResult = deviceMapper.deleteByPrimaryKey(id);
        if (deviceResult == 1) {
            //删除成功,删除redis中的数据,进行缓存同步
            if (redisTemplate.hasKey(DEVICE_BACKUP)) {
                redisTemplate.delete(DEVICE_BACKUP);
            }
            //设备已经删除,删除设备详细信息
            deviceInfoMapper.deleteInfoByDeviceId(id);
            //删除设备与数据指标关联表
            deviceInfoMapper.deleteIndexByDeviceId(id);
        }
        return deviceResult;
    }

    /**
     * 批量删除
     *
     * @param ids 设备id集合
     */
    @Override
    @Transactional
    public void deleteAll(List<Long> ids) {

        if (ids != null && ids.size() > 0) {
            for (Long id : ids) {
                int deviceResult = deviceMapper.deleteByPrimaryKey(id);
                if (deviceResult == 1) {
                    //设备已经删除,删除设备详细信息
                    deviceInfoMapper.deleteInfoByDeviceId(id);
                    //删除设备与数据指标关联表
                    deviceInfoMapper.deleteIndexByDeviceId(id);
                }
            }
        }
        //删除成功,删除redis中的数据,进行缓存同步
        if (redisTemplate.hasKey(DEVICE_BACKUP)) {
            redisTemplate.delete(DEVICE_BACKUP);
        }
    }

}


